#pragma once

#include <stack>
#include <vector>

#include "./baseCommandManager.hpp"

namespace qbe::undoRedoT {

#define EVENT_UNDOREDOSTATECHANGED 1

struct UndoRedoPool {
  std::stack<BaseCommand*> stackUndo;
  std::stack<BaseCommand*> stackRedo;

  bool is_change_saved = true;
};

class BaseCommand;

class CommandManager : public BaseCommandManager {
  class UndoRedoStateInspector {
    friend class CommandManager;

   private:
    UndoRedoStateInspector(CommandManager* pCommandManager);
    ~UndoRedoStateInspector();

   private:
    CommandManager* m_pCommandManager;
    bool m_bUndoable;
    bool m_bRedoable;
  };

 private:
  CommandManager();
  ~CommandManager();
  CommandManager(const CommandManager& rhs);
  CommandManager& operator=(const CommandManager& rhs);

 public:
  static CommandManager* Instance();

  bool CallCommand(BaseCommand* pCommand);
  void ClearAllCommands();

  void Undo();
  void Redo();
  bool CanUndo() const;
  bool CanRedo() const;
  BaseCommand* UndoCommand();
  BaseCommand* RedoCommand();

  void switchUndoRedo(unsigned index);
  unsigned createUndoRedoPool();

  void setChangeSaved(bool is_change_save, unsigned index);
  bool getChangeSaved();

  UndoRedoPool* getUndoRedoPool(unsigned index);

 private:
  void PushUndoCommand(BaseCommand* pCommand);
  BaseCommand* PopUndoCommand();
  void PushRedoCommand(BaseCommand* pCommand);
  BaseCommand* PopRedoCommand();
  void DeleteUndoCommands();
  void DeleteRedoCommands();
  void limitStep(std::stack<BaseCommand*>& m_stack);

 private:
  std::stack<BaseCommand*> stackUndo;
  std::stack<BaseCommand*> stackRedo;

  bool is_change_saved = true;  //修改的数据是否被保存过
  int max_step = 50;

  std::vector<UndoRedoPool*> undo_redo_pools;
  int current_undo_redo_index = 0;
};
}  // namespace qbe::undoRedoT